package com.riguz.forks.framework;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.riguz.forks.framework.mvc.ExceptionHandler;
import com.riguz.forks.framework.mvc.HandlerInvoker;
import com.riguz.forks.framework.mvc.Request;
import com.riguz.forks.framework.mvc.RequestContext;
import com.riguz.forks.framework.mvc.Result;
import com.riguz.forks.framework.mvc.ViewResolver;
import com.riguz.forks.framework.route.Route;
import com.riguz.forks.framework.route.RouteHandler;
import com.riguz.forks.framework.util.ServletUtil;

public class DispatcherServlet extends HttpServlet {
    private static final long   serialVersionUID = 6436182046292687218L;
    private static final Logger logger           = LoggerFactory.getLogger(DispatcherServlet.class);

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding(Framework.ENCODING);

        String method = request.getMethod();
        String path = ServletUtil.getRequestPath(request);

        // RouteHanlderMapping mapping = new RouteHanlderMapping();
        logger.debug("[forks] => {}:{} thread[{}]", method, path, Thread.currentThread().getId());

        Route r = Framework.getRoute();

        RouteHandler handler = r.resolve(new Request(method, path));
        if (handler == null) {
            logger.warn("Not resolved");
            response.sendError(404, "Requested path not resolved");
            return;
        }
        List<String> params = handler.getParameters();
        logger.debug("params:{}", params);

        HandlerInvoker invoker = Framework.getHandlerInvoker();
        ViewResolver resolver = Framework.getViewResolver();
        ExceptionHandler exceptionHandler = Framework.getExceptionHandler();
        try (RequestContext context = new RequestContext(request, response)) {
            try {
                Result result = invoker.invoke(request, handler);
                resolver.resolveView(request, response, result);
            } catch (Exception e) {
                exceptionHandler.handleException(request, response, e);
            }
        }
    }
}
